(library (data-abstraction)
  (export get-all-effects
          get-all-means-of-transportation
          get-travelers
          get:traveler/route
          get:event-groups
          get:event-group/events
          ;; get:next-route-part
          ;; get:route-part/from
          ;; get:route-part/to
          ;; get:route-part/transportation
          )
  (import
    (except (rnrs base) let-values map error)
    (only (guile)
          lambda* λ
          map)
    (srfi srfi-1)
    ;; custom libraries
    (lib user-input-output)
    (lib list-procs)
    (lib alist-procs)
    (lib set)
    (prefix (lib logger) log:)
    (model)))

;; ================
;; DATA ABSTRACTION
;; ================

;; The goal of these procedures is to ease changes of data
;; structures for example for configuration objects, by
;; providing ways of accessing the data structures for other
;; parts of the program to use. If all other parts of the
;; program only make use of the data abstraction procedures,
;; then one can change the data structure and only adapt
;; these procedures, to get back to a working program,
;; instead of having to modify the whole program.

(define get-all-effects
  (λ (story-params)
    (define items (alist-ref story-params "transportation"))
    (define events
      (apply append
             (map (λ (item)
                    (vector->list (alist-ref (rest item) "events")))
                  items)))
    (define effects
      (apply append
             (map (λ (event)
                    (vector->list (alist-ref event "effects")))
                  events)))
    (set->list (list->set effects))))


(define get-all-means-of-transportation
  (λ (transportation-configs)
    (map (λ (entry) (first entry))
         transportation-configs)))


(define get-travelers
  (λ (players)
    (map (λ (entry) (first entry))
         players)))


(define get:traveler/route
  (λ (traveler-config)
    (vector->list (alist-ref (rest traveler-config) "route"))))


(define get:event-groups
  (λ (transportations-config transportation)
    (alist-nested-refs transportations-config `(,transportation "events")
     #:default
     (λ ()
       (log:debug (string-format "using fallback transportation for ~a" transportation))
       (alist-nested-refs transportations-config `("default" "events"))))))


(define get:event-group/events
  (λ (event-group)
    (log:debug (string-format "getting events from event group ~a" event-group))
    (vector->list (rest event-group))))


(define get:next-route-part
  (λ (route)
    (first route)))


(define get:route-part/from
  (λ (route-part)
    (alist-ref route-part "from")))

(define get:route-part/to
  (λ (route-part)
    (alist-ref route-part "to")))

(define get:route-part/transportation
  (λ (route-part)
    (alist-ref route-part "transportation")))
